package org.springblade.modules.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.modules.admin.entity.ElevatorDetail;
import org.springblade.modules.admin.service.ElevatorService;
import org.springblade.modules.admin.service.IElevatorDetailService;
import org.springblade.modules.admin.service.IElevatorNumService;
import org.springblade.modules.admin.utils.GenerateElevatorNumService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Nonnull;
import java.util.*;
import java.util.concurrent.*;

/**
 * 电梯快速识别码 service
 *
 * @author: Sharry
 * @createTime: 2023/4/19 13:57
 * @version: Version-1.0
 */
@Slf4j
@Service
@EnableScheduling
public class ElevatorNumServiceImpl implements IElevatorNumService {

	@Autowired
	private TransactionTemplate transactionTemplate;

	@Autowired
	private GenerateElevatorNumService gens;

	@Autowired
	private IElevatorDetailService eds;

	@Autowired
	private ElevatorService es;

	/**
	 * 现有电梯 批量执行 唯一识别码 脚本，用完就删
	 */
	@Override
	@TenantIgnore
	public void generateElevatorNumBatch() {
		//*. 打桩 输出 总耗时
		long n = System.currentTimeMillis();
		Date now = new Date(n);
		log.info("当前系统时间：{}", now);

		//1. 创建定时线程池，用于定时任务执行
		ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(5);

		//2. 创建定时任务、批量阈值
		int batchNum = 200;

		TimerTask t = new TimerTask() {
			@Override
			public void run() {
				String threadName = Thread.currentThread().getName();
				List<ElevatorDetail> edList = es.listWithoutEleNum();
				log.info("创建FutureTask：{}", threadName);

				// 获取全部 未删除电梯的电梯详情， 且唯一识别码尚未插入
				List<ElevatorDetail> batchList;
				// 批量截取
				if (edList.size() > batchNum) {
					batchList = edList.subList(0, batchNum - 1);
				} else if(edList.size() > 1) {
					batchList = edList.subList(0, edList.size() - 1);
				} else {
					batchList = edList;
				}

				// 生成唯一识别码
				if (ObjectUtil.isNotEmpty(batchList)) {
					batchList.forEach(b -> b.setElevatorNum(gens.generateElevatorNum(b.getElevatorId())));
				}

				// 编程式事务
				transactionTemplate.execute(new TransactionCallbackWithoutResult() {
					@Override
					protected void doInTransactionWithoutResult(@Nonnull TransactionStatus transactionStatus) {
						// 批量新增
						eds.saveOrUpdateBatch(batchList);
					}
				});

				// 本次任务结束，打印日志
				log.info("本次任务结束，更新了{}条数据",batchList.size());
				int leftSize = es.listWithoutEleNum().size();
				log.info("剩余任务数：{}",leftSize);

				// *. 打桩输出
				long a = System.currentTimeMillis();
				Date after = new Date(a);
				log.info("执行完毕，系统时间{}", after);
				long time = a - n;
				log.info("共执行了{}秒", time / 1000);
			}
		};

		// 3. 定时执行
		threadPool.schedule(t, 11, TimeUnit.SECONDS);

		// 4. 关闭定时线程池
		threadPool.shutdown();
	}

	@Override
	@TenantIgnore
	public String getEleNumById(Long elevatorId) {
		return
			eds.getOne(
				new LambdaQueryWrapper<ElevatorDetail>()
					.eq(ElevatorDetail::getElevatorId,elevatorId))
				.getElevatorNum();
	}

}
